package tests;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;

import TecMaster.Cliente;
import TecMaster.Empresa;
import TecMaster.GDA;
import TecMaster.Equipamentos.Computador;
import TecMaster.Equipamentos.Equipamento;
import TecMaster.Equipamentos.Tv;
import TecMaster.Equipamentos.Equipamento.DefeitosMaisComuns;
import TecMaster.Equipamentos.Equipamento.MarcasAutorizadas;

import static org.junit.Assert.*;

/**
 * Testes de Empresa.
 * 
 * @author Theocrito & Flavio.
 * 
 */
public class TesteEmpresa {
	Empresa<Equipamento> emp1;

	Cliente c1;
	Cliente c2;

	Equipamento equip1;
	Equipamento equip2;

	@Before
	public void setUp() throws Exception {
		emp1 = new Empresa<Equipamento>();
		equip1 = new Tv(MarcasAutorizadas.LG, DefeitosMaisComuns.NAO_LIGA,
				"001", 2, true, 0);
		equip2 = new Computador(MarcasAutorizadas.LG,
				DefeitosMaisComuns.NAO_LIGA, "002", 4, false, 7);
		c1 = new Cliente("Tom", "Rua Nascimento Silva, 107", "10475475612");
		c2 = new Cliente("Carlos", "Rua dos pombos, 0", "23423534501");
	}

	@Test(expected = IllegalArgumentException.class)
	public void testaAddClienteEEquipamentoNomeNull()
			throws FileNotFoundException, IOException {
		emp1.addClienteEEquipamento(null, equip1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testaAddClienteEEquipamentoEquipamentoNull()
			throws FileNotFoundException, IOException {
		emp1.addClienteEEquipamento(c1, null);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testaAddEquipamentoCpfNull() throws FileNotFoundException,
			IOException {
		emp1.addEquipamento(null, equip1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testaAddEquipamentoEquipamentoNull()
			throws FileNotFoundException, IOException {
		emp1.addEquipamento(c1.getCpf(), null);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testaAddEquipamentoCpfVazio() throws FileNotFoundException,
			IOException {
		emp1.addEquipamento("", equip1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void testaAddEquipamentoCpfInvalido() throws FileNotFoundException,
			IOException {
		emp1.addEquipamento("123456789013", equip1);
		emp1.addEquipamento("1234567890", equip1);
		emp1.addEquipamento("123456s8901", equip1);
	}

	@Test
	public void testaAddClienteEEquipamento() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		assertTrue(emp1.addClienteEEquipamento(c1, equip1));
		assertFalse(emp1.addClienteEEquipamento(c1, equip2));
		assertEquals("Tamanho do mapa errado", 1, emp1
				.getMapaClientesEquipamentos().size());
		assertTrue(emp1.addClienteEEquipamento(c2, equip2));
		assertEquals("Tamanho do mapa errado", 2, emp1.numeroDeClientes());
	}

	@Test
	public void testaAddEquipamento() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		assertTrue(emp1.addClienteEEquipamento(c1, equip1));
		assertEquals("Numero de equipamentos do cliente errado", 1, emp1
				.getEquipamentosDoCliente(c1).size());
		assertTrue(emp1.addEquipamento("10475475612", equip2));
		assertEquals("Numero de equipamentos do cliente errado", 2, emp1
				.getEquipamentosDoCliente(c1).size());
		assertFalse(emp1.addEquipamento("23423534501", equip2));
	}

	@Test
	public void testaGetEquipamentoDoCliente() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addClienteEEquipamento(c2, equip2);
		List<Equipamento> equipamentoC1 = new ArrayList<Equipamento>();
		equipamentoC1.add(equip1);
		List<Equipamento> equipamentoC2 = new ArrayList<Equipamento>();
		equipamentoC2.add(equip2);
		assertEquals("Lista errada", equipamentoC1, emp1
				.getEquipamentosDoCliente(c1));
		assertEquals("Lista errada", equipamentoC2, emp1
				.getEquipamentosDoCliente(c2));
		assertEquals("tamanho errado na lista", 1, equipamentoC1.size());
	}

	@Test
	public void testaLocalizaCliente() throws Exception {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addClienteEEquipamento(c2, equip2);
		assertEquals("Cliente nao encontrado", c1, emp1
				.localizaCliente("10475475612"));
		assertEquals("Cliente nao encontrado", c2, emp1
				.localizaCliente("23423534501"));
	}

	@Test
	public void testaGetClientePeloEquipamento() throws Exception {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addClienteEEquipamento(c2, equip2);
		assertEquals("cliente nao encontrado", c1, emp1
				.getClientePeloEquipamento(equip1));
		assertEquals("Cliente nao encontrado", c1, emp1
				.getClientePeloEquipamento(equip1));
	}

	@Test
	public void testaRemoveEquipamentoCliente() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addEquipamento("10475475612", equip2);
		assertTrue("Equipamento nao removido", emp1.removeEquipamentoCliente(
				c1, equip1));
		assertEquals(1, emp1.getEquipamentosDoCliente(c1).size());
		assertFalse(emp1.removeEquipamentoCliente(c1, equip1));
		assertTrue("Equipamento nao removido", emp1.removeEquipamentoCliente(
				c1, equip2));
		assertEquals(0, emp1.getEquipamentosDoCliente(c1).size());
	}

	@Test
	public void testaRemoveCliente() throws FileNotFoundException, IOException,
			ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();

		emp1.addClienteEEquipamento(c1, equip1);
		assertTrue("Cliente nao foi removido", emp1.removeCliente(c1));
		assertFalse("Cliente nao deveria ser removido", emp1.removeCliente(c2));
	}

	@Test
	public void testaOrdenacaoPorData() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();

		emp1.addClienteEEquipamento(c2, equip1);
		emp1.addClienteEEquipamento(c1, equip2);

		Calendar data1 = new GregorianCalendar();
		data1.add(Calendar.DAY_OF_YEAR, 15);
		List<Equipamento> listaOrdenada = emp1
				.ordenacaoPorData(data1);
		assertEquals("nao deveia haver equiamentos", 0, listaOrdenada.size());

		equip1.setEstado(Equipamento.EstadoDoEquipamento.CONSERTADO);
		equip2.setEstado(Equipamento.EstadoDoEquipamento.CONSERTADO);

		List<Equipamento> listaOrdenada2 = emp1
				.ordenacaoPorData(data1);
		assertEquals("Deveria haver 2 equipamentos", 2, listaOrdenada2.size());
		assertEquals(equip1, listaOrdenada2.get(0));

		Calendar data2 = new GregorianCalendar();
		data2.add(Calendar.DAY_OF_YEAR, 7);
		List<Equipamento> listaOrdenada3 = emp1
				.ordenacaoPorData(data2);
		assertEquals("Deveria haver 1 equipamento", 1, listaOrdenada3.size());
		assertEquals(equip1, listaOrdenada2.get(0));
	}

	@Test
	public void testaOrdenacaoNomeCliente() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();

		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addClienteEEquipamento(c2, equip2);

		Map<Cliente, ArrayList<Equipamento>> mapOrdenado = emp1
				.ordenacaoNomeCliente();
		assertEquals("Tamanho errado", 2, mapOrdenado.size());

		equip1.setEstado(Equipamento.EstadoDoEquipamento.CONSERTADO);

		Map<Cliente, ArrayList<Equipamento>> mapOrdenado2 = emp1
				.ordenacaoNomeCliente();
		assertEquals("Tamanho errado", 1, mapOrdenado2.size());
	}

	@Test
	public void testaOrdenacaoTipoAparelho() throws Exception {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();

		Equipamento equip3 = new Tv(MarcasAutorizadas.SAMSUNG,
				DefeitosMaisComuns.SEM_SINAL_AUDIO, "005", 2, true, 0);
		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addClienteEEquipamento(c2, equip2);
		emp1.addEquipamento("23423534501", equip3);

		Map<Cliente, ArrayList<Equipamento>> mapOrdenado = emp1
				.ordenacaoTipoAparelho(equip1.getClass());

		assertEquals("Tamanho errado", 2, mapOrdenado.size());
	}

	@Test
	public void testaOrdenacaoGarantia() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addClienteEEquipamento(c2, equip2);

		List<HashMap<Equipamento, Cliente>> listaOrdenada = emp1
				.ordencaoGarantia();

		assertEquals(
				"O tamanho do map dos equipamentos que estao na garantia deveria ser 1",
				1, listaOrdenada.get(0).size());
		assertEquals(
				"O tamanho do map dos equipamentos que nao estao na garantia deveria ser 1",
				1, listaOrdenada.get(1).size());
	}

	@Test
	public void testaOrdenaDefeitoApresentado() throws FileNotFoundException,
			IOException, ClassNotFoundException {
		GDA<Equipamento> gda = new GDA<Equipamento>();
		gda.resetarCadastros();
		emp1 = new Empresa<Equipamento>();
		emp1.addClienteEEquipamento(c1, equip1);
		emp1.addClienteEEquipamento(c2, equip2);

		HashMap<Equipamento, Integer> mapOrdenado = emp1
				.ordenacaoDefeitoApresentado();

		assertEquals("O defeito do equipamento deveria ser 1", new Integer(1),
				mapOrdenado.get(equip1));
		assertEquals("O defeito do equipamento deveria ser 1", new Integer(1),
				mapOrdenado.get(equip2));
	}
}
